﻿#!/usr/bin/python
# coding=utf-8

import urllib
import urllib2
import webbrowser
import json
import urlparse
import sys
import poster
import os
import time
import pickle

# weibo.py
# author: Ban Guijun
# Date: 2013/4


# text length of a single weibo
WEIBOLENGTH = 140

# console encode
inputEncode = sys.stdin.encoding
outputEncode = sys.stdout.encoding


class WeiboConsole:
	
	
	accessToken = ''		
	
	#=======================
	#app info
	#=======================
	appKey = ''
	appSecret = ''
	redirectUri = ''
	
	def __init__(self):
		self.accessToken = self.authorize()
		
	
	# user login to authorize textWeibo to use its' info
	def login(self):
		#log in automatically
		#method: post	
		userAgent = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'
		#loginUrl = "https://api.weibo.com/oauth2/authorize?response_typy=code&redirect_uri=https%3A%2F%2Fapi.weibo.com%2Foauth2%2Fdefault.html&client_id=1609670037"
		loginUrl = "https://api.weibo.com/oauth2/authorize"
		#loginUrl = "https://api.weibo.com"
		loginData = urllib.urlencode({'userId': username, 
			'passwd': pwd, 
				'action': 'login',
					'display': 'default',
						'withOfficalFlag': '0',
							'withOfficalAccount': '',
								'scope': '',
									'ticket': '',
										'isLoginSina': '',
											'response_type': 'code',
												'regCallback': 'https%3A%2F%2Fapi.weibo.com%2F2%2Foauth2%2Fauthorize%3Fclient_id%3D1609670037%26response_type%3Dcode%26display%3Ddefault%26redirect_uri%3Dhttps%3A%2F%2Fapi.weibo.com%2Foauth2%2Fdefault.html%26from%3D%26with_cookie%3D',
													'redirect_uri': redirectUri,
														'client_id': appKey,
															'appkey62': '2AEzCl',
																'state': '',
																	'verifyToken': 'null',
																		'from': ''})
		directRequest = urllib2.Request(loginUrl, loginData)
		directRequest.add_header('User-Agent', userAgent)
		directRequest.add_header('Accept', 'text/html, application/xhtml+xml, */*')
		directRequest.add_header('Content', 'application/x-www-form-urlencoded')
		directRequest.add_header('Accept-Encoding', 'gzip, deflate')
		directData = urllib2.urlopen(urllib2.Request(loginUrl, loginData))
		directReturnUrl = directData.geturl()
		print 'Response url:', directReturnUrl
		code = urlparse.urlparse(directReturnUrl)[3]
		print 'get code:', code
		return code
	
	def retriveAccessToken(self):
		#=======================
		#othth 2.0 module
		#=======================
		#stage1: direct user to get access code
		directPostData = urllib.urlencode({'client_id': self.appKey, 'response_typy': 'code', 'redirect_uri': self.redirectUri})
		directUrl= 'https://api.weibo.com/oauth2/authorize?'
		directReturn = urllib2.urlopen(urllib2.Request(directUrl, directPostData))
	
		webbrowser.open_new_tab(directUrl + directPostData)
		#user login to get code
		#code = login()
		code = raw_input("Input your Code:")
	
		# exchange for AccessToken
		accessTokenUrl = 'https://api.weibo.com/oauth2/access_token'
		accessTokenData = urllib.urlencode({'client_id': self.appKey,
			'client_secret': self.appSecret,
				'grant_type': 'authorization_code',
					'redirect_uri': self.redirectUri,
						'code': code})
		accessTokenReturn = urllib2.urlopen(urllib2.Request(accessTokenUrl, accessTokenData)).read()
		accessToken = json.JSONDecoder().decode(accessTokenReturn)['access_token']
		print 'Access Token:', accessToken
		accessTokenFileWrite = open('accessTokenFile.txt', 'w')
		accessTokenData = {'time': time.time(), 'accessToken': accessToken}
		pickle.dump(accessTokenData, accessTokenFileWrite)
		accessTokenFileWrite.close()
		return accessToken
	
	# oauth2 authorization, return code
	def authorize(self):
		if 'accessTokenFile.txt' in os.listdir('.'):
			accessTokenFileRead = open('accessTokenFile.txt', 'r')
			accessTokenRead = pickle.load(accessTokenFileRead)
			elapsedTime = time.time() - accessTokenRead['time']
			if elapsedTime/3600 < 24:
				accessToken = accessTokenRead['accessToken']
				accessTokenFileRead.close()
				
			else:				
				accessToken = self.retriveAccessToken()
		else:
			accessToken = self.retriveAccessToken()			
		return accessToken
				



	def showUser(self, user):
		print '=========================================='
		print '用户名：\t*', 
		print '介绍：\t*', user['user']['description'].encode(outputEncode, 'replace')
		print '注册时间：\t*', user['user']['created_at'].encode(outputEncode)
		print '粉丝数：\t*', user['user']['followers_count']
		print '关注数：\t*', user['user']['favourites_count']
		print '城市：\t*', user['user']['location'].encode(outputEncode, 'replace')
		print '==========================================='


	def showWeibo(self, weibo):
		print '============================================='
		print '用户名：\t*', weibo['user']['name'].encode(outputEncode, 'replace')
		print '微博：\t*', weibo['text'].encode(outputEncode, 'replace')
		if weibo.has_key('retweeted_status'):
			originRetweeted = weibo['retweeted_status']
			print '*******Retweeted*******'
			print '原微博：\t*', weibo['retweeted_status']['text'].encode(outputEncode, 'replace')
			if originRetweeted.has_key('comments_count') and originRetweeted.has_key('reposts_count'):
				print '评论及转发数：\t*', weibo['retweeted_status']['comments_count'], '\t', weibo['retweeted_status']['reposts_count']
			print '***Retweete end*******'
		if weibo.has_key('original_pic'):
			print '图片地址：\t*', weibo['original_pic']
		print '发表时间：\t*', weibo['created_at'].encode(outputEncode)
		print '地理位置：\t*', weibo['geo']
		print '评论数：\t*', weibo['comments_count']
		print '转发数：\t*', weibo['reposts_count']
		print '============================================='
	
	
	
	
	
	
	
	# use weibo api to get weibo
	
	# get friend time line
	def getFriendsTimeLine(self):
		friendsTimeLineUrl = 'https://api.weibo.com/2/statuses/friends_timeline.json'
		friendsTimeLineData = urllib.urlencode({'access_token': self.accessToken})
		friendsTimeLineReturn = urllib2.urlopen(friendsTimeLineUrl + '?' + friendsTimeLineData)	#GET way
		friendsTimeLineList = json.JSONDecoder().decode(friendsTimeLineReturn.read())
		#print json.dumps(friendsWeibo, sort_keys = True, indent = 4)
		#friendsTimelineFile = open('friendsTimelineFile.txt', 'w')
		#friendsTimelineFile.write(json.dumps(friendsTimelineWeibo, sort_keys = True, indent = 4))
		#friendsTimelineFile.close()
		#print type(friendsTimelineWeibo)
		#friendsTimelineList = json.dumps(friendsTimelineWeibo, sort_keys = True, indent = 4)
		print type(friendsTimeLineList)
		for friend in friendsTimeLineList['statuses']:
			self.showUser(friend)
			
			
			
	# get the latest public weibo, number = 20
	def getPublicTimeLine(self, returnCount = 20):
		publicTimeLineUrl = 'https://api.weibo.com/2/statuses/public_timeline.json'
		publicTimeLineData = urllib.urlencode({'access_token': self.accessToken, 'count': returnCount})
		publicTimeLineReturn = urllib2.urlopen(publicTimeLineUrl + '?' + publicTimeLineData)	#GET way
		publicTimeLineList = json.JSONDecoder().decode(publicTimeLineReturn.read())
		for publicWeibo in publicTimeLineList['statuses']:
			self.showWeibo(publicWeibo)
			
	# get login users' and friends' latest weibo
	def getHomeTimeLine(self, returnCount = 20):
		homeTimeLineUrl = 'https://api.weibo.com/2/statuses/home_timeline.json'
		homeTimeLineData = urllib.urlencode({'access_token': self.accessToken, \
			'since_id': 0, 'max_id': 0, 'count': returnCount, \
				'page': 1, 'base_app':0, 'feature': 0, 'trim_user': 0})
		homeTimeLineReturn = urllib2.urlopen(homeTimeLineUrl + '?' + homeTimeLineData)	#GET
		homeTimeLineList = json.JSONDecoder().decode(homeTimeLineReturn.read())
		for homeWeibo in homeTimeLineList['statuses']:
			self.showWeibo(homeWeibo)
	
	
	# get given user's weibo
	def getUserTimeLine(self, returnCount = 20):
		userTimeLineUrl = 'https://api.weibo.com/2/statuses/user_timeline.json'
		userName = raw_input("Please input user name:\n").decode(inputEncode)
		userTimeLineData = urllib.urlencode({'access_token': self.accessToken, \
			'uid': 0, 'screen_name': userName.encode('utf8'), \
				'since_id': 0, 'max_id': 0, 'count': returnCount, \
					'page': 1, 'base_app': 0, 'feature': 0, 'trim_user': 0})		
		userTimeLineReturn = urllib2.urlopen(userTimeLineUrl + '?' + userTimeLineData)
		userTimeLineList = json.JSONDecoder().decode(userTimeLineReturn.read())
		for userWeibo in userTimeLineList['statuses']:
			#print userName.encode(outputEncode)," latest Weibo:\n"
			self.showWeibo(userWeibo)
	
	
	
	# update a weibo, text and picture
	def uploadWeibo(self, uploadInput = 'Weibo Test', uploadImage = 'test.jpg'):			
		uploadUrl = 'https://api.weibo.com/2/statuses/upload.json'
		#uploadInput = raw_input("Please input your content:")
		#uploadImage = raw_input("Please input your image name:")
		poster.streaminghttp.register_openers()	
		if isinstance(uploadInput, str):
			uploadContent = unicode(uploadInput, inputEncode)		# change into unicode
		elif isinstance(uploadInput, unicode):
			uploadContent = uploadInput
		uploadData = {'access_token': self.accessToken, \
			'status': uploadContent.encode('utf-8'), \
				'pic':open(uploadImage, 'rb'), \
					'visible': 0, 'lat': 0.0, 'long': 0.0}
		datagen, headers = poster.encode.multipart_encode(uploadData)
		uploadRequest = urllib2.Request(uploadUrl, datagen, headers)
	#	uploadRequest.add_header('User-Agent', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)')
	#	uploadRequest.add_header('Content-Type', 'multipart/form-data')
		uploadReturn = urllib2.urlopen(uploadRequest)		# request: POST
		uploadList = json.JSONDecoder().decode(uploadReturn.read())
		print "A new weibo updated success! Content:\n"
		print urllib.unquote(uploadList['text']).encode(outputEncode, 'replace')
		if uploadList.has_key('thumbnail_pic') or uploadList.has_ke('bmiddle_pic') or uploadList.has_key('original_pic'):
			print 'Upload image suceess! Image url:', uploadList['original_pic']
		print 'Update time:\t*\t', uploadList['created_at'].encode(outputEncode, 'replace')
		
		
	# update a weibo, only text	
	def updateWeibo(self, updateInput = 'Weibo Test'):
		updateUrl = 'https://api.weibo.com/2/statuses/update.json'
		#updateInput = raw_input("Please input your content:")
		#print updateInput
		if isinstance(updateInput, str):
			updateContent = unicode(updateInput, inputEncode)		# change into unicode
		elif isinstance(updateInput, unicode):
			updateContent = updateInput
		updateData = urllib.urlencode({'access_token': self.accessToken, \
			'status': updateContent.encode('utf-8'), \
				'visible': 0, 'lat': 0.0, 'long': 0.0})
		updateReturn = urllib2.urlopen(urllib2.Request(updateUrl, updateData))		# request: POST
		updateList = json.JSONDecoder().decode(updateReturn.read())
		print "A new weibo updated success! Content:\n"
		print urllib.unquote(updateList['text']).encode(outputEncode, 'replace')
		print 'Update time:\t*\t', updateList['created_at'].encode(outputEncode, 'replace')
		
	def sendWeibo(self, text='Weibo Test.'):
		text = raw_input("Please input your content:\n")
		imageName = raw_input("Please input the name (WITH EXTENSION!!!) of your image:")
		if imageName not in os.listdir('.'):
			print "No image named ", imageName, "!. Only text will be sent."
			isImage = 0
		else:
			isImage = 1
		if text == '':
			text = 'Send Weibo'
		textUnicode = unicode(text, inputEncode)		# trans into unicode
		textLength = len(textUnicode)
		
		# send weibo with/without image according length
		if textLength >= WEIBOLENGTH*2:
			if textLength >= WEIBOLENGTH*3:
				print "Content too long. Truncate for 3 weibo."
			weibo1 = '(1)' + textUnicode[0:WEIBOLENGTH-4]
			if isImage == 0:
				self.updateWeibo(weibo1)
			elif isImage == 1:
				self.uploadWeibo(weibo1, imageName)
			weibo2 = '(2)' + textUnicode[WEIBOLENGTH-3:2*WEIBOLENGTH-1]
			self.updateWeibo(weibo2)
			weibo3 = '(3)' + textUnicode[2*WEIBOLENGTH:-1]
			self.updateWeibo(weibo3)
		if textLength >= WEIBOLENGTH and textLength < WEIBOLENGTH*2:
			weibo1 = '(1)' + textUnicode[0:WEIBOLENGTH-4]
			if isImage == 0:
				self.updateWeibo(weibo1)
			elif isImage == 1:
				self.uploadWeibo(weibo1, imageName)
			weibo2 = '(2)' + textUnicode[WEIBOLENGTH-3:-1]
			self.updateWeibo(weibo2)
		if textLength >0 and len(textUnicode)<WEIBOLENGTH:
			if isImage == 0:
				self.updateWeibo(textUnicode)
			elif isImage == 1:
				self.uploadWeibo(textUnicode, imageName)
		
		


	def show(self):
		print "This is TextWeibo, with which you can read and send your sina weibo."
		helpInfo = '''
		How to use?
		===================================
		Hit these button to use:
		0:\t send a weibo
		1:\t get latest public weibo
		2:\t get latest blogged friends
		3:\t get latest users and friends weibo
		4:\t get given users weibo
		5:\t send a weibo with picture
		===================================
		'''
		while(1):
			print helpInfo
			userCommand = raw_input("Please hit a button to use, hit Q to quit\n")
			if userCommand == '1':
				self.getPublicTimeLine()
			elif userCommand == '2':
				self.getFriendsTimeLine()
			elif userCommand == '3':
				self.getHomeTimeLine()
			elif userCommand == '4':
				self.getUserTimeLine()
			elif userCommand == '0':
				self.sendWeibo()					
			elif userCommand == 'q' or userCommand == 'Q':
				print 'quit!'
				break
			
			print '************************************'
			print '************************************'
			


if __name__ == '__main__':
	weiboConsole = WeiboConsole()
	weiboConsole.show()
